package com.ftg.learn.filter;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair;
import com.ftg.learn.util.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * 全局过滤器，处理令牌
 * @author kangjx
 */
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {

    //加密盐
    @Value("${secretKey:!@#$%^&*}")
    private String secretKey;

    //认证者
    @Value("${issuser:kangjx}")
    private String issuser;

    @Value("${default.login.path}")
    private String defaultLogin;

    /**
     *    redis处理
     */
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 令牌缓存前缀说明，用来存储redis里面的 生成前缀key
     */
    private static final String TOKEN_CACHE_PREFIX = "auth-service:";

    /**
     * 重写过滤功能
     * @param exchange web服务发起变化
     * @param chain  网关过滤器
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest serverHttpRequest = exchange.getRequest();
        ServerHttpResponse serverHttpResponse = exchange.getResponse();

        /**
         * 前端通过head传递token时 信息的key
         */
        String token = serverHttpRequest.getHeaders().getFirst("token");

        /**
         * 没有令牌的情况
         */
        String apiPath = serverHttpRequest.getURI().getPath();

        /**
         * 登陆获得令牌操作
         *    第一次访问的时候，如果是getToken那么我们要放行
         *    其它操作我们要验证
         */
//        if(defaultLogin.equalsIgnoreCase(apiPath)){
//            return chain.filter(exchange);
//        }
//
//        if (StringUtils.isBlank(token)) {
//            serverHttpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);
//            return getVoidMono(serverHttpResponse, ResponseCodeEnum.TOKEN_MISSION);
//        }
//
//        // 检查是否可以解密
//        String username = null;
//        try {
//            username = JWTUtil.getUserInfo(token);
//        } catch (JWTDecodeException e) {
//            return getVoidMono(serverHttpResponse, ResponseCodeEnum.TOKEN_INVALID);
//        }
//
//        /**
//         * 令牌不能解析的情况
//         */
//        if (StringUtils.isEmpty(username)) {
//            return getVoidMono(serverHttpResponse, ResponseCodeEnum.TOKEN_INVALID);
//        }
//
//        // 检查Redis中是否有此Token
//        String key = MD5Util.getMD5Str(username);
//        if (!redisTemplate.opsForHash().hasKey(TOKEN_CACHE_PREFIX + key, "token")) {
//            return getVoidMono(serverHttpResponse, ResponseCodeEnum.TOKEN_INVALID);
//        }
//
//        try {
//            JWTUtil.verifyToken(issuser, token, secretKey);
//        } catch (TokenAuthenticationException ex) {
//            return getVoidMono(serverHttpResponse, ResponseCodeEnum.TOKEN_INVALID);
//        } catch (Exception ex) {
//            return getVoidMono(serverHttpResponse, ResponseCodeEnum.UNKNOWN_ERROR);
//        }

        return chain.filter(exchange);
    }


    private Mono<Void> getVoidMono(ServerHttpResponse serverHttpResponse, ResponseCodeEnum responseCodeEnum) {
        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        ResponseResult responseResult = ResponseResult.builder()
                .code(responseCodeEnum.getCode())
                .msg(responseCodeEnum.getMessage())
                .build();
        DataBuffer dataBuffer = serverHttpResponse.bufferFactory().wrap(JSON.toJSONString(responseResult).getBytes());
        return serverHttpResponse.writeWith(Flux.just(dataBuffer));
    }


    @Override
    public int getOrder() {
        return 0;
    }
}
